/*!
 * Stars
 * A simple index page
 * https://gitee.com/milkpotatoes/stars
 * Copyright (c) 2025 milkpotatoes
 * MIT License
 */

import { Widget } from "./widget.js";

export class Shortcut {
    static SHORTCUT_TYPE_SHORTCUT = 0;
    static SHORTCUT_TYPE_WIDGET = 1;
    _url;
    _parent
    elm;

    _name;
    _icon;
    _desc;
    widget = null;
    type = Shortcut.SHORTCUT_TYPE_SHORTCUT;
    get url() {
        return this._url;
    }
    set url(url) {
        if (this.type === Shortcut.SHORTCUT_TYPE_WIDGET) {
            if (location.protocol === 'https') {
                const mUrl = new URL(url);
                if (mUrl.protocol !== 'https') {
                    throw new Error('cannot use "http" widgets under "https" web.')
                }
            }
            if (this.widget) {
                this.widget.setUrl(url);
            }
        } else {
            if (this.widget) {
                this.widget.destroy();
                this.widget = null;
            }
        }
        this._url = url;
    }
    get name() {
        return this._name;
    };
    set name(value) {
        this._name = value;
        this.elm.querySelector('.name').textContent = value;
    };
    get icon() {
        return this._icon;
    };
    set icon(value) {
        this._icon = value;
        this.elm.querySelector('img.icon').src = value;
    };
    get desc() {
        return this._desc;
    };
    set desc(value) {
        this._desc = value;
        if (this.parent) {
            this.elm.title = value;
        } else {
            this.elm.querySelector('.shortcut').title = value;
        }
    };

    set parent(parent) {
        this._parent = parent;
        this.elm = this.elm.querySelector('.shortcut');
        parent.append(this);
        this.setListener();
    };
    get parent() {
        return this._parent;
    };

    setClickEvent() {
        this.elm.addEventListener('mousedown', function (e) {
            if (e.target.closest('.action') ||
                e.target.classList.contains('indicator') ||
                e.target.classList.contains('add-shortcut')) {
                return;
            };
            this.open(e.buttons);
        }.bind(this));
    }

    setEditEvent() {
        this.elm.querySelector('.action>.edit').addEventListener('click', function (e) {
            this.edit();
            e.preventDefault();
            e.stopPropagation();
        }.bind(this));
    }

    setDeleteEvent() {
        this.elm.querySelector('.action>.delete').addEventListener('click', function (e) {
            this.remove();
            e.preventDefault();
            e.stopPropagation();
        }.bind(this), { once: true });
        this.elm._remove = this.elm.remove;
        this.elm.remove = this.remove.bind(this);
    }

    setDraggableEvent() {
        this.elm.querySelector('.indicator').addEventListener('mouseenter', function (e) {
            this.elm.setAttribute('draggable', true);
            this.elm.querySelector('.action').style.display = 'none';
            e.preventDefault();
            e.stopPropagation();
        }.bind(this));
        this.elm.querySelector('.indicator').addEventListener('mouseleave', function (e) {
            this.elm.removeAttribute('draggable');
            this.elm.querySelector('.action').style.display = '';
            e.preventDefault();
            e.stopPropagation();
        }.bind(this));
    }

    setDragEvent() {
        const dragImg = new Image(48, 48);
        dragImg.style.objectFit = 'contain';
        const dragIcon = document.createElement('canvas');
        dragIcon.height = 48;
        dragIcon.width = 48;
        const ctx = dragIcon.getContext('2d');
        dragImg.onload = () => {
            ctx.drawImage(dragImg, 0, 0, 48, 48);
        };
        dragImg.src = this._icon;

        this.elm.addEventListener('dragstart', function (e) {
            e.dataTransfer.setData('text/uri-list', this.url);
            e.dataTransfer.setData('text/plain', `${this._name} ${this.url}`);
            dragIcon.style.top = '100%';
            document.body.append(dragIcon)
            dragIcon.style.position = 'fixed';
            e.dataTransfer.setDragImage(dragIcon, 0, 0);
            setTimeout(() => {
                this.elm.classList.add('dragging');
                dragIcon.remove();
            }, 50);
            e.dataTransfer.effectAllowed = 'all';
        }.bind(this));
        this.elm.addEventListener('dragend', function () {
            this.elm.classList.remove('dragging');
        }.bind(this));
    }

    setListener() {
        this.setClickEvent();
        this.setDeleteEvent();
        this.setEditEvent();
        this.setDraggableEvent();
        this.setDragEvent();
    }

    constructor(name, url, icon, desc = '', parent, type = Shortcut.SHORTCUT_TYPE_SHORTCUT) {
        this.elm = document.querySelector('.shortcuts template').content.cloneNode(true);
        this.name = name;
        this.url = url;
        const icon_ = icon ? icon : new URL(url).origin + '/favicon.ico';
        this.icon = icon_;
        this.desc = desc;
        this.type = type;
        if (parent) {
            this.parent = parent;
        };
        this.elm.data = this;
    }

    bind(collection) {
        this.parent = collection;
    }

    open(mouseButton = 1) {
        if (this.url) {
            for (let i = 0; i < this.parent.size() - 1; i++) {
                const widget = this.parent.at(i).widget;
                if (widget && widget !== this.widget && !widget.pined) {
                    widget.hide();
                }
            }
            switch (this.type) {
                case Shortcut.SHORTCUT_TYPE_WIDGET:
                    const box = this.elm.getBoundingClientRect();
                    const { x, y, width: w, height: h } = box
                    if (this.widget === null) {
                        this.widget = new Widget(this.name, this.url, w * 2 + 24, h * 2 + 24);
                    }
                    if (mouseButton === 1) {
                        this.widget.show(x + w / 2, y + h / 2);
                    } else if (mouseButton === 4) {
                        this.widget.popup(x, y);
                    }
                    break;
                case Shortcut.SHORTCUT_TYPE_SHORTCUT:
                default:
                    if (mouseButton === 1) {
                        window.open(this.url, '_top');
                    } else if (mouseButton === 4) {
                        window.open(this.url, '_blank');
                    }
                    break;
            }
        }
    }

    remove() {
        if (this.parent) {
            for (let i = 0; i < this.parent.size(); i++) {
                if (this.parent.at(i) === this) {
                    this.parent.remove(i);
                    break;
                }
            }
            this.elm._remove();
        }
    }

    edit() {
        if (this.parent) {
            for (let i = 0; i < this.parent.size(); i++) {
                if (this.parent.at(i) === this) {
                    this.parent.edit(i);
                    break;
                }
            }
        }
    }
}
